package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"strings"
)

type arrayFlags []string

func (i *arrayFlags) String() string {
	return "my string representation"
}

func (i *arrayFlags) Set(value string) error {
	*i = append(*i, value)
	return nil
}

var (
	PORT      = 8080
	FROM_LIST []string
	TO_LIST   []string
	//RSA
	PUB_KEY      []byte
	PRI_KEY      []byte
	PUB_KEY_PATH string
	PRI_KEY_PATH string
	//加密方式
	ENCRYPT_TYPE string

	//最大加密限制
	ENCRYPT_MAX_SIZE int

	//加密头
	ENCRYPT_CONTENT_TYPE     arrayFlags
	ENCRYPT_CONTENT_TYPE_MAP map[string]bool
)

func init() {
	var fromToList arrayFlags
	flag.IntVar(&PORT, "p", 8080, "port")
	flag.Var(&fromToList, "l", "proxy list")
	flag.StringVar(&PUB_KEY_PATH, "pub", "", "rsa public key")
	flag.StringVar(&PRI_KEY_PATH, "pri", "", "rsa private key")
	flag.StringVar(&ENCRYPT_TYPE, "t", "", "encrypt type: only supports rsa")
	flag.IntVar(&ENCRYPT_MAX_SIZE, "ms", 0, "max encrypt size")
	flag.Var(&ENCRYPT_CONTENT_TYPE, "c", "content type which should be encrypted")
	flag.Parse()

	for _, v := range fromToList {
		i := strings.Index(v, ":")
		if i == -1 {
			continue
		}
		FROM_LIST = append(FROM_LIST, v[:i])
		TO_LIST = append(TO_LIST, v[i+1:])
	}

	ENCRYPT_CONTENT_TYPE_MAP = make(map[string]bool)
	for _, v := range ENCRYPT_CONTENT_TYPE {
		ENCRYPT_CONTENT_TYPE_MAP[v] = true
	}

	//rsa
	if strings.EqualFold(ENCRYPT_TYPE, "rsa") {
		var err error
		PRI_KEY, err = ioutil.ReadFile(PRI_KEY_PATH)
		if err != nil {
			log.Fatal("private key file read error")
		}
		PUB_KEY, err = ioutil.ReadFile(PUB_KEY_PATH)
		if err != nil {
			log.Fatal("public key file read error")
		}
	}

}

func main() {
	var port = fmt.Sprintf(":%d", PORT)
	srv := &http.Server{
		Addr:    port,
		Handler: http.HandlerFunc(Handler()),
	}
	err := srv.ListenAndServe()
	if err != nil {
		pid := PortInUse(PORT)
		if pid != -1 {
			Kill(strconv.Itoa(pid))
			_ = srv.ListenAndServe()
		}
	}

	//log.Println(PROXY_LIST)
}
